package com.ljx.stream.stream04;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author LJX
 * @Description: TODO
 * @Date: 2022/11/5 16:37
 * @Version 1.0
 */
public class StreamTest1 {
	public static void main(String[] args) {
		List<Student> list = new ArrayList<>();
		Collections.addAll(list,new Student("李吉祥",18,'男'),
				new Student("李吉星",28,'男') ,
				new Student("李吉",18,'女'),
				new Student("吉祥",38,'女'));

		// 利用stream流过滤年龄大于18岁的学生
		// map-接受lambda，将元素转换成其他形式或者提取信息，接受一个函数作为参数，该函数会被应用到每个元素，并将其映射成一个新的元素、
		list.stream().filter(e->e.getAge()<28).map(e->e.getName()).forEach(System.out::println);
		// sort排序操作 (如果传入的数据不是单一的，我们需要为sorted里面传入比较规则)
		list.parallelStream().sorted((e,t)->e.getAge()-t.getAge()).count();
		// 流也可以进行合并concat()，去重distinct()，限制limit()，跳过skip()等中间操作
		ArrayList<Integer> arrayList = new ArrayList<>();
		Collections.addAll(arrayList,12,34,123,12);
		ArrayList<Integer> arrayList1 = new ArrayList<>();
		Collections.addAll(arrayList1,12,34,123,12);
		// Stream流里面有一个合并流的方法(流,流);,他是一个中间操作
		Stream.concat(arrayList.stream(),arrayList1.stream()).count();
		// find操作--findFirst和findAny(返回一个option类型的不是返回一个stream流)终止操作
		Optional<Student> first = list.stream().findFirst();
		System.out.println(first);
		//  parallelStream是合并流而stream是并行流
		Optional<Integer> any1 = arrayList.stream().findAny();
		System.out.println(any1);
		Optional<Integer> any = arrayList.parallelStream().findAny();
		System.out.println(any);
		//  match 匹配操作--allMatch(传入断言式接口函数,返回布尔类型) anyMatch
		boolean b = list.stream().allMatch(e -> e.getAge() > 40);
		System.out.println(b);
		boolean b1 = list.stream().anyMatch(e -> e.getName().length() > 3);
		System.out.println(b1);
		// 聚合函数操作(终止操作) max,min(传入一个比较器comparator),count
		Optional<Student> min = list.stream().min((o1, o2) -> o1.getAge() - o2.getAge());
		System.out.println(min);
		Optional<Student> max = list.stream().min((o1, o2) -> o2.getAge() - o1.getAge());
		System.out.println(max);

		// 规约操作reduce ,规约也称之为缩减，顾名思义，是把一个流缩减为一个值，能实现对集合的求和求积，求大小值
		// 求和
		Optional<Integer> reduce = arrayList.stream().reduce((e, t) -> e += t);
		System.out.println(reduce);
		// 求积
		Optional<Integer> reduce1 = arrayList.stream().reduce((e, t) -> e *= t);
		System.out.println(reduce1);
		// 求最大值
		Optional<Integer> reduce3 = arrayList.stream().reduce((e, t) -> e-t<0? e:t);
		System.out.println(reduce3);
		/**
		 *### collect搜集操作(终止操作)
		 *
		 * > 计数： count
		 * >
		 * > 平均值： averagingInt、 averagingLong、 averagingDouble
		 * >
		 * > 最值： maxBy、 minBy
		 * >
		 * > 求和： summingInt、 summingLong、 summingDouble
		 */
		// 求数据个数
		Long collect = list.stream().collect(Collectors.counting());
		System.out.println(collect);
		// 求平均值（传入一个函数型函数式接口）
		Double collect1 = list.stream().collect(Collectors.averagingInt(e -> e.getAge()));
		System.out.println(collect1);
		// 求最大值最小值(需要传入一个比较器comparator)
		Optional<Student> collect2 = list.stream().collect(Collectors.maxBy((o1, o2) -> o1.getAge() - o2.getAge()));
		System.out.println(collect2);
		Optional<Student> collect3 = list.stream().collect(Collectors.minBy((o1, o2) -> o2.getAge() - o1.getAge()));
		System.out.println(collect3);
		// 求和传入一个函数型函数式接口
		list.stream().collect(Collectors.summingInt(e->e.getAge()));
		System.out.println(collect2);

		// 搜索为一个新的list集合
		List<Character> collect4 = list.stream().map(e -> e.getSex()).collect(Collectors.toList());
		System.out.println(collect4);

		// 搜索为一个set集合
		Set<Character> collect5 = list.stream().map(e -> e.getSex()).collect(Collectors.toSet());
		System.out.println(collect5);
		// 搜索为一个map集合toMap有两个参数key value()并且都需要传入函数式接口
		Map<String, Integer> collect6 = list.stream().collect(Collectors.toMap(e -> e.getName(), e -> e.getAge()));
		System.out.println(collect6);
		// 分组操作传入函数式接口意思为以什么条件分组
		Map<String, List<Student>> collect7 = list.stream().collect(Collectors.groupingBy(e -> e.getName()));
		System.out.println(collect7);

	}
}

@Data
@AllArgsConstructor
@NoArgsConstructor
class Student{
	private String name;
	private Integer age;
	private  char sex;
}
